# encoding=utf-8
# socket通信客户端
# BingoLee 2024-04-21
import json
import struct
import socket


class SocketClient:
    """
    socket短连接通信类
    """
    buf_size = 4096
    head_fmt = '16si800s'  # 发送的头部数据结构 bytes(16), int, bytes(800)
    head_size = struct.calcsize(head_fmt)

    @classmethod
    def send_message(cls, svr_info: tuple, oper: str, data: str = '') -> str:
        """
        发送文本消息接口
        """
        data = data.encode()
        data_size = len(data)
        offset_count = 0
        head = struct.pack(cls.head_fmt, oper.encode(), data_size, b'')
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            sock.connect(svr_info)
            sock.sendall(head)
            while data_size >= cls.buf_size:
                sock.sendall(data[offset_count * cls.buf_size: (offset_count + 1) * cls.buf_size])
                data_size -= cls.buf_size
                offset_count += 1
            sock.sendall(data[-data_size:])

            res = struct.unpack(cls.head_fmt, sock.recv(cls.head_size))
            # print('response: %s, %s, %s' % (res[0].decode().rstrip('\0'), res[1], res[2].decode().rstrip('\0')))
            result = res[2].decode().rstrip('\0')
            if result != oper:   # 无效的数据，客户端服务端定义的此数据要一致
                return None, "invalid data"
            back_data = b''
            if res[1] != 0:  # 服务端存在回复的数据，需要接收
                while len(back_data) < res[1]:
                    back_data += sock.recv(cls.buf_size)
        except Exception as e:
            return None, str(e)
        finally:
            sock.close()
        return back_data.decode(), None
